from dicRead import dicRead
  
def pivot(fname, noOfPivots):
    
    d = dicRead(fname)
    isUnbounded = False
    (m_by_n, basicIndices, nonbasicIndices, bVec, aMat, cVec ) = d
    print 'Original ', m_by_n, basicIndices, nonbasicIndices, bVec, aMat, cVec
    tmpcVec = [val1 for val1 in cVec if val1 < 0]
    if len(tmpcVec) != 0 and cVec[0] == 0:
        print 'Initialization is needed'
        m_by_n[0], m_by_n[1] = m_by_n[1], m_by_n[0]
        tt = basicIndices
        basicIndices = nonbasicIndices
        nonbasicIndices = tt
        aMat = zip(*aMat)
        aMatNew = []
        for i in range(int(m_by_n[0])):
            aMatColNew = []
            for j in range(int(m_by_n[1])):
                aMatColNew.append(- aMat[i][j])
            aMatNew.append(aMatColNew)
        
        aMat = aMatNew
        
        cVecNew = []
        cVecNew.append(0.0)
        for v in bVec:
            cVecNew.append(-v)
        cVec = cVecNew        
    
        bVecNew = []
        for i in range(len(basicIndices)):
            bVecNew.append(1)
        bVec = bVecNew
        print 'Initialized ', m_by_n, basicIndices, nonbasicIndices, bVec, aMat, cVec
    
    if noOfPivots > 1:
        fileNameStep = fname.split('.')[0] + '.step'+str(noOfPivots)+'_output'
    else:
        fileNameStep = fname + '.step'+str(noOfPivots)+'_output'
    fo = open(fileNameStep, 'w')
    
    enteringArrIdx = 0
    for i, x in enumerate(cVec):
        if i == 0:
            continue
        if x > 0:
            enteringArrIdx = i
            break
    coeff = 0
    ii = 0
    unbounded = True
    for i, x in enumerate(bVec):
        if x != 0:        
            if (aMat[i][enteringArrIdx-1] < 0 and aMat[i][enteringArrIdx-1]/x < coeff):
                coeff = aMat[i][enteringArrIdx-1]/x
                ii = i
                unbounded = False
        else:
            if (aMat[i][enteringArrIdx-1] < 0):
                ii = i
                unbounded = False
    if (unbounded):
        print 'Unbounded'
        isUnbounded = True
    
    if(not isUnbounded):
        tempIdx = basicIndices[ii]
        basicIndices[ii] = nonbasicIndices[enteringArrIdx-1]
        nonbasicIndices[enteringArrIdx-1] = tempIdx
        coeffTemp = -aMat[ii][enteringArrIdx-1]
        aMat[ii][enteringArrIdx-1] = -1.0 
        bVec[ii] = bVec[ii]/coeffTemp
        for i in range(len(aMat[ii])):
            aMat[ii][i] = aMat[ii][i]/coeffTemp
        
        for rowi in range(len(aMat)):
            coefRow = aMat[rowi][enteringArrIdx-1]         
            if rowi != ii:
                aMat[rowi][enteringArrIdx-1] = 0.0
                for lcol in range(len(aMat[rowi])):
                    aMat[rowi][lcol] = aMat[rowi][lcol] + aMat[ii][lcol]*coefRow
                bVec[rowi] = bVec[rowi]+ bVec[ii]*coefRow
        
        cVec[0] = bVec[ii]*cVec[enteringArrIdx]+cVec[0]
        
        for lcol in range(len(nonbasicIndices)):
            if lcol+1 != enteringArrIdx :
                cVec[lcol+1] = cVec[lcol+1] + cVec[enteringArrIdx]*aMat[ii][lcol]
        
        cVec[enteringArrIdx] = cVec[enteringArrIdx]*aMat[ii][enteringArrIdx-1]
                        
        print 'No Of Pivots', noOfPivots

        fo.write(' '.join(map(str,m_by_n)))
        fo.write('\n')
        fo.write(' '.join(map(str,basicIndices)))
        fo.write('\n')
        fo.write(' '.join(map(str,nonbasicIndices)))
        fo.write('\n')
        fo.write(' '.join(map(str,bVec)))
        
        for rowline in aMat:
            fo.write('\n')
            fo.write(' '.join(map(str,rowline)))
        fo.write('\n')
        fo.write(' '.join(map(str,cVec)))
        fo.close()
        
        for pvtCnt in range(1, len(cVec)):
            if cVec[pvtCnt] > 0:
                pivot(fileNameStep, noOfPivots+1)
            else:
                fo2 = open(fname.split('.')[0]+'.out', 'w')
                fo2.write(str(cVec[0]))                
                fo2.write('\n')
                fo2.write(str(noOfPivots))
                fo2.close()

        print 'Modified ', m_by_n, basicIndices, nonbasicIndices, bVec, aMat, cVec
        print 'm_by_n, basicIndices, nonbasicIndices, bVec, aMat, cVec'
        
        tmpCvec = cVec[1:]
        tmpVec = [val1 for val1 in tmpCvec if val1 > 0]
        if len(tmpVec) == 0:
            print 'Reverting to primal'
            m_by_n[0], m_by_n[1] = m_by_n[1], m_by_n[0]
            tt1 = basicIndices
            basicIndices = nonbasicIndices
            nonbasicIndices = tt1
            aMat = zip(*aMat)
            aMatNew1 = []
            for i in range(int(m_by_n[0])):
                aMatColNew1 = []
                for j in range(int(m_by_n[1])):
                    aMatColNew1.append(- aMat[i][j])
                aMatNew1.append(aMatColNew1)

            aMat = aMatNew1

            cVecNew1 = []
            cVecNew1.append(0.0)
            for v in bVec:
                cVecNew1.append(-v)
            cVec = cVecNew1

            bVecNew1 = []
            for i in range(len(basicIndices)):
                bVecNew1.append(-tmpCvec[i])
            bVec = bVecNew1
            print 'Reverted ', m_by_n, basicIndices, nonbasicIndices, bVec, aMat, cVec
            #lets read original file again
            fnameTemp = fname.split(".")[0]+".dict"
            (m_by_n_drop, basicIndices_drop, nonbasicIndices_reread, bVec_drop, aMat_drop, cVec_reread) = dicRead(fnameTemp)
            print basicIndices, nonbasicIndices_reread, cVec_reread
            idxarr = []
            mularr = []
            for i in nonbasicIndices_reread:
                if (i in basicIndices):
                    idx = basicIndices.index(i)
                    idxarr.append(idx)
                    cVec[0] = cVec[0] + cVec_reread[int(i)]*bVec[idx]
                    mularr.append(cVec_reread[int(i)])
            print 'cVec[0]', cVec[0]
            for i in range(len(nonbasicIndices)):            
                ttt1 = 0
                for k in range(len(idxarr)):
                    ttt1 = ttt1 + mularr[k]*aMat[idxarr[k]][i]
                if nonbasicIndices[i] in nonbasicIndices_reread:
                    cVec[i+1] = cVec_reread[int(nonbasicIndices[i])] + ttt1
                else:
                    cVec[i+1] = ttt1
            print 'nonbasicIndices', nonbasicIndices
            print 'cVec', cVec
            
            fo3 = open(fname.split('.')[0]+".dict.init", 'w')
            
            fo3.write(' '.join(map(str,m_by_n)))
            fo3.write('\n')
            fo3.write(' '.join(map(str,basicIndices)))
            fo3.write('\n')
            fo3.write(' '.join(map(str,nonbasicIndices)))
            fo3.write('\n')
            fo3.write(' '.join(map(str,bVec)))
            
            for rowline in aMat:
                fo3.write('\n')
                fo3.write(' '.join(map(str,rowline)))
            fo3.write('\n')
            fo3.write(' '.join(map(str,cVec)))
            fo3.close()
        
        exit(0)


if __name__ == '__main__':
    
    fname = 'assignmentParts/part1.dict'
    pivot(fname, 1)